#! /usr/bin/env/python3
# coding:UTF-8
'''
    名称：掷骰子
    作者：王楠
    版本: 4.0
    日期：2020/03/01
    功能：dice_num，几个骰子
         3.0: 数据可视化 散点图 plt.scatter
         4.0: 直方图 plt.hist
         5.0：科学计算 numpy np
'''
import random
import matplotlib.pyplot as plt
import numpy as np

font = {'family': 'SimSun', 'weight': 'bold', 'size': '10'}
plt.rc('font', **font)  # 步骤一（设置字体的更多属性）
plt.rc('axes', unicode_minus=False)  # 步骤二（解决坐标轴负数的负号显示问题）

# plt.rcParams['font.sans-serif'] = ['SimSun']  # 步骤一（替换sans-serif字体）
# plt.rcParams['axes.unicode_minus'] = False    # 步骤二（解决坐标轴负数的负号显示问题）


class Dice():
    '''
    骰子对象
    '''
    def roll_dice(self):
        numeral = random.randint(1, 6)
        return numeral


def tick_X(dice_num):
    '''
        根据骰子个数，生成点数的x轴标签
    '''
    xtick_lables = ['']*6*dice_num               # 生成坐标
    for i in range(6*dice_num):
        xtick_lables[i] = str(i+1)+'点'
    # print(xtick_lables)
    tick_pos = np.arange(dice_num, 6*dice_num+1) + 0.5   # 坐标的位置，并向右偏移0.5
    return tick_pos, xtick_lables


def dice_main():

    result_sum_list = []  # 记录点数之和
    dice_case_list = []  # 记录骰子对象
    roll_times = int(input('请输入投掷次数：'))
    dice_num = int(input('请输入骰子个数：'))
    numeral_list = [[] for i in range(dice_num)]  # 存放每一个骰子每次的点数 相当于二维数组
    print(numeral_list)
    result_list_times = [0] * (6 * dice_num - dice_num + 1)
    result_list_numeral = list(range(dice_num,
                                     6 * dice_num + 1))  # 根据骰子个数确定可能出现的点数的list
    result_dict = dict(zip(result_list_numeral, result_list_times))
    for i in range(dice_num):
        dice_case_list.append(Dice())
    for i in range(roll_times):
        sum_of_dices = 0
        for n in range(dice_num):
            numeral_list[n].append(dice_case_list[n].roll_dice())
            sum_of_dices += numeral_list[n][i]
        for x in result_list_numeral:
            if sum_of_dices == x:
                result_dict[x] += 1
                result_sum_list.append(x)
    # print(numeral_list)
    # print(result_sum_list)
    print('{}个骰子，投掷了{}次：'.format(dice_num, roll_times))
    # for result_num in result_list_numeral:
    #     print('出现点数{0}的次数是{1}次,频率是{2:.1f}%'.format(
    #         result_num, result_dict[result_num],
    #         result_dict[result_num] / roll_times * 100))
    # print('{}个骰子，投掷了{}次：'.format(dice_num, roll_times))
    for result_num, result_times in result_dict.items():
        print('出现点数{0}的次数是{1}次,频率是{2:.1f}%'.format(
            result_num, result_times, result_times / roll_times * 100))
    # 数据可视化
    colors = ['red', 'b', 'white', 'green', '#fb320e']
    x_list = list(range(1, roll_times + 1))
    tick_pos, xtick_lables = tick_X(dice_num)   # 设置坐标标签 点数
    # 输出方式选择
    fig = plt.figure(num='掷骰子统计图', figsize=(10, 10))
    ax1 = fig.add_subplot(221)
    ax1.set_title('单个骰子散点分布图 ')  # 设置标题
    plt.xlabel('投掷次数')  # 设置X轴标签
    plt.ylabel('每个骰子骰子点数')  # 设置Y轴标签
    plt.legend('x1')  # 设置图标
    for i in range(dice_num):
        y_list = numeral_list[i]
        ax1.scatter(x_list, y_list, c=colors[i], alpha=0.5)
    ax2 = fig.add_subplot(223)
    ax2.set_title('点数和散点分布图 ')  # 设置标题
    plt.xlabel('投掷次数')  # 设置X轴标签
    plt.ylabel('骰子点数和')  # 设置Y轴标签
    plt.legend('x2')  # 设置图标
    x_ax1 = list(range(1, roll_times + 1))
    y_ax2 = result_sum_list
    ax2.scatter(x_ax1, y_ax2)
    ax3 = fig.add_subplot(222)
    ax3.set_title('点数和直方图')
    plt.xticks(tick_pos, xtick_lables)
    plt.xlabel('点数')
    plt.ylabel('出现的次数')
    ax3.hist(result_sum_list,
             bins=range(dice_num, 6 * dice_num + 2),
             edgecolor='black',
             linewidth=1)
    ax4 = fig.add_subplot(224)
    ax4.set_title('点数和直方图')
    plt.xticks(tick_pos, xtick_lables)
    plt.xlabel('点数')
    plt.ylabel('出现的频率')
    ax4.hist(result_sum_list,
             bins=range(dice_num, 6 * dice_num + 2),
             normed=1,
             edgecolor='black',
             linewidth=1)
    plt.show()


def dice_main_mp():
    '''
    采用np的random实现掷骰子，不需要dice类创建，直接创建随机数
    '''
    roll_times = int(input('请输入投掷次数：'))
    dice_num = int(input('请输入骰子个数：'))

    # 根据骰子个数和投掷次数生成arrry 矩阵，矩阵里的数字为1-6的随机
    roll_arr = np.random.randint(1, 7, size=(dice_num, roll_times))
    # 测试
    # print(roll_arr)
    # print(roll_arr[0, 2])  # 读取第0列第2行的位置
    # print(roll_arr[[0, 2]])  # 读取第0行和第2行
    # print(roll_arr[:, [0, 2, 4]])  # 读取某一列，或者某几列roll_arr[:, [1, 3]] 第1列和第三列
    # print(list(roll_arr[0]))
    # sum_arr = roll_arr.sum()
    # sum_arr0 = roll_arr.sum(0)
    # sum_arr1 = roll_arr.sum(1)
    # print('sum():', sum_arr)
    # print('sum(0):', sum_arr0)
    # print('sum(1):', sum_arr1)
    # 对矩阵每一列求和，：生成投掷次数个数的一维矩阵
    sum_arr = roll_arr.sum(0)
    print('{}个骰子，投掷了{}次：'.format(dice_num, roll_times))
    sum_arr_list = list(sum_arr)
    print(sum_arr_list)
    for result_num in range(dice_num, 6*dice_num + 1):
        result_times = 0
        for i in range(roll_times):
            if result_num == sum_arr_list[i]:
                result_times += 1
        print('出现点数{0}的次数是{1}次,频率是{2:.1f}%'.format(
            result_num, result_times,
            result_times / roll_times * 100))
    # 数据可视化
    colors = ['red', 'b', 'white', 'green', '#fb320e']
    x_list = list(range(1, roll_times + 1))
    tick_pos, xtick_lables = tick_X(dice_num)   # 设置坐标标签
    # 输出方式选择
    fig = plt.figure(num='掷骰子统计图', figsize=(10, 10))
    # 第一个fig上的第一个图
    ax1 = fig.add_subplot(221)
    ax1.set_title('单个骰子散点分布图 ')  # 设置标题
    plt.xlabel('投掷次数')  # 设置X轴标签
    plt.ylabel('每个骰子骰子点数')  # 设置Y轴标签
    plt.legend('x1')  # 设置图标
    for i in range(dice_num):
        y_list = list(roll_arr[i])
        # print(y_list)
        ax1.scatter(x_list, y_list, c=colors[i], alpha=0.5)
    # 第一个fig上的第二个图
    ax2 = fig.add_subplot(223)
    ax2.set_title('点数和散点分布图 ')  # 设置标题
    plt.xlabel('投掷次数')  # 设置X轴标签
    plt.ylabel('骰子点数和')  # 设置Y轴标签
    plt.legend('x2')  # 设置图标
    x_ax2 = list(range(1, roll_times + 1))
    y_ax2 = list(sum_arr)
    ax2.scatter(x_ax2, y_ax2)
    # 第一个fig上的第三个图
    ax3 = fig.add_subplot(222)
    ax3.set_title('点数和直方图')
    plt.xticks(tick_pos, xtick_lables)
    plt.xlabel('点数')
    plt.ylabel('出现的次数')
    ax3.hist(list(sum_arr),
             bins=range(dice_num, 6 * dice_num + 2),
             edgecolor='black',
             linewidth=1)
    # 第一个fig上的第四个图
    ax4 = fig.add_subplot(224)
    ax4.set_title('点数和直方图')
    plt.xticks(tick_pos, xtick_lables)
    plt.xlabel('点数')
    plt.ylabel('出现的频率')
    ax4.hist(list(sum_arr),
             bins=range(dice_num, 6 * dice_num + 2),
             normed=1,
             edgecolor='black',
             linewidth=1)
    # 第二个fig
    fig1 = plt.figure(num='掷骰子统计图(histogram())', figsize=(5, 5))
    bx1 = fig1.add_subplot(111)
    # hist，bins = np.histogram(sum_arr, bins=range(dice_num, 6 * dice_num + 2))
    # print(hist)
    # print(bins)
    bx1.set_title('点数和直方图')
    plt.xticks(tick_pos, xtick_lables)
    plt.xlabel('点数')
    plt.ylabel('出现的频率')
    bx1.hist(sum_arr, bins=range(dice_num, 6 * dice_num + 2),
             normed=1,
             edgecolor='black',
             linewidth=1)
    plt.show()


if __name__ == '__main__':
    print('##################np实现：###########################')
    dice_main_mp()
    print('×××××××××××××××普通实现：××××××××××××××××××')
    dice_main()
